#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

#define START   100
#define END     300
#define CNT     4

static int cnt;
static pthread_mutex_t cnt_mut = PTHREAD_MUTEX_INITIALIZER;

static int job;
static pthread_mutex_t job_mut = PTHREAD_MUTEX_INITIALIZER;


int is_prime(int num);
static void *thr_job(void *arg);

int main(void)
{
    pthread_t tid[CNT];
    int err, i;

    for (i = 0; i < CNT; i++) {
        err = pthread_create(tid + i, NULL, thr_job, NULL);
        if (err) {
            fprintf(stderr, "pthread_create():%s", strerror(err));
            return 1;
        }
    }

    // 发放任务
    for (i = START; i <= END; i++) {
        pthread_mutex_lock(&job_mut);

        while (job > 0) {
            pthread_mutex_unlock(&job_mut);
            pthread_mutex_lock(&job_mut);
        }

        job = i;
        pthread_mutex_unlock(&job_mut);
    }


    pthread_mutex_lock(&job_mut);
    while (job > 0) {
        pthread_mutex_unlock(&job_mut);
        pthread_mutex_lock(&job_mut);
    }
    job = -1;
    pthread_mutex_unlock(&job_mut);


    for (i = 0; i < CNT; i++)
        pthread_join(tid[i], NULL);

    pthread_mutex_destroy(&job_mut);
    pthread_mutex_destroy(&cnt_mut);

    printf("\n共有 %d 个质数\n", cnt);

    return 0;
}

int is_prime(int num)
{
    int i;
    if (num < 2)
        return 0;

    for (i = 2; i <= num / i; i++) {
        if (num % i == 0)
            return 0;
    }

    return 1;
}

static void *thr_job(void *arg)
{
    int value;

    while (1) {
        pthread_mutex_lock(&job_mut);

        while (0 == job) {
            pthread_mutex_unlock(&job_mut);
            pthread_mutex_lock(&job_mut);
        }

        if (-1 == job) {
            pthread_mutex_unlock(&job_mut);
            break;    
        }

        value = job;
        job = 0;
        pthread_mutex_unlock(&job_mut);

        if (is_prime(value)) {
            printf("%d ", value);
            pthread_mutex_lock(&cnt_mut);
            cnt++;
            pthread_mutex_unlock(&cnt_mut);
        }
    }

    return (void *)0;
}

